﻿using DotNetty.Buffers;
using DotNetty.Codecs;
using DotNetty.Transport.Channels;
using QQ.Client;
using QQ.Packet;
using QQ.Packet.Request;
using QQ.Packet.Request.TLV;
using QQ.Packet.Response.TLV;
using QQ.Utils;
using System.Collections.Generic;
using static System.Console;

namespace QQ.Codecs
{
    public class wtlogin_login_decoder : MessageToMessageDecoder<Packet.Response.OICQResponse>
    {
        public override bool IsSharable => true;

        private readonly LoginSigInfo loginSigInfo;
        private readonly QQDeviceConfig config;
        private readonly OICQRequest oicqRequest;
        private readonly SSOFrame ssoFrame;
        private readonly HeadPacket headPacket;
        private readonly ClientCallback clientCallback;

        public wtlogin_login_decoder(ClientCallback clientCallback, HeadPacket headPacket, SSOFrame ssoFrame, OICQRequest oicqRequest, QQDeviceConfig config, LoginSigInfo loginSigInfo)
        {
            this.headPacket = headPacket;
            this.ssoFrame = ssoFrame;
            this.oicqRequest = oicqRequest;
            this.loginSigInfo = loginSigInfo;
            this.config = config;
            this.clientCallback = clientCallback;
        }

        protected override void Decode(IChannelHandlerContext context, Packet.Response.OICQResponse msg, List<object> output)
        {
            var buffer = msg.plainBody;
            Packet.wtlogin_login wtlogin = new Packet.wtlogin_login();
            wtlogin.Deserialize(buffer);
            WriteLine($"登录结果：{wtlogin.loginRet}");
            foreach (var item in wtlogin.tlvs)
            {
                WriteLine($"键值：{item.Key}，长度：{item.Value.ReadableBytes}");
            }
            if (wtlogin.loginRet == 0)
            {
                WriteLine("登录成功");
                wtlogin.tlvs[281] = QQTea.Decrypt(wtlogin.tlvs[281].ToArray(), config.TgtgKey.ToArray()).ToByteBuffer();
                var ret = wtlogin.tlvs[281].ReadTLVS();
                loginSigInfo.tgt = ret[0x10a];
                loginSigInfo.tgtKey = ret[0x10d];
                loginSigInfo.sKey = ret[0x120];
                loginSigInfo.d2 = ret[0x143];
                loginSigInfo.d2Key = ret[0x305];
                //loginSigInfo.
                //TODO unimplement so many
                TLV0x11a tlv0x11a = new TLV0x11a(config);
                tlv0x11a.Deserialize(ret[0x11a]);
                WriteLine($"年龄：{tlv0x11a.age}\n性别：{tlv0x11a.gender}\n昵称：{tlv0x11a.nick}");

                clientCallback.wtlogin_callback();
            }
            else
            {
                //key = 260(0x104) onSMSVerifyNeeded DeviceLockLogin
                //0x402 
                if (wtlogin.loginRet == 160)
                {
                    WriteLine(wtlogin.tlvs[516].GetString());//a url to login verify
                }
                else if (wtlogin.loginRet == 204)
                {
                    //device lock login
                    //context.Channel.WriteAndFlushAsync(DeviceLockLogin(wtlogin.tlvs[0x104],wtlogin.tlvs[0x402]));
                    WriteLine("设备锁登录");
                }
                else
                {
                    var tmp = wtlogin.tlvs[326];
                    tmp.SkipBytes(4);
                    WriteLine(tmp.ReadBytesWithLength().GetString());
                    WriteLine(tmp.ReadBytesWithLength().GetString());
                    WriteLine(tmp.ReadBytesWithLength().GetString());
                }
            }
        }

        private IByteBuffer DeviceLockLogin(IByteBuffer t104, IByteBuffer t402)
        {
            throw new System.Exception("还没实现呢");
            wtlogin_login wtlogin = new wtlogin_login()
            {
                subCommand = 20,
                tlvs = new Dictionary<short, IByteBuffer>()
                {
                    {0x8,new TLV0x8().Serialize()},
                    //{0x104,new TLV0x104().Serialize()},
                    //{0x8,new TLV0x116().Serialize()},
                    //{0x8,new TLV0x401().Serialize()},
                }
            };
            oicqRequest.cmd = 0x810;
            oicqRequest.uin = (int)loginSigInfo.uin;
            oicqRequest.PlainBody = wtlogin.Serialize();

            ssoFrame.cmdName = "wtlogin.login";
            ssoFrame.body = oicqRequest.Serialize();

            headPacket.encryptType = Packet.HeadPacket.EncryptType.ZERO;
            headPacket.body = ssoFrame.Serialize();
            headPacket.packetType = 0x0A;
            return headPacket.Serialize();
        }
    }
}
